/************ Private Header Files **************/
#include "HsTypes.h"
#include "PhyDebug.h"
#include "PhyStruct.h"
#include "PmdGlobals.h"
#include "PhyConstants.h"
#include "tables.h"
#include "tx_functions.h"
#include "iqdma_3500.h"
#include "icrdefs_3500.h"
#include "txtables.h"
#include "thread_globals.h"
#include "threads_common.h"//add 627

static inline hs_int32_t
wait_buffer(
				hs_int32_t subbuff_toggle,
				hs_int16_t **psTxOutDtoAPtrI,
				hs_int16_t **psTxOutDtoAPtrQ,
				hs_int16_t *psTxDtoAStartI,
				hs_int16_t *psTxDtoAStartQ
			)
{
	/** Wait till prev sub-buffer is Txmitted **/
	#ifndef PHY_RX_CYCLE_PRINT
	wait_sub_buffer_filled();
	reset_sub_buffer_interrupt();
	#endif

	subbuff_toggle ^= 1;

	if(subbuff_toggle){
		*psTxOutDtoAPtrI = psTxDtoAStartI + SUB_BUF_SIZE_TX;
		*psTxOutDtoAPtrQ = psTxDtoAStartQ + SUB_BUF_SIZE_TX;
	}
	else{
		*psTxOutDtoAPtrI = psTxDtoAStartI;
		*psTxOutDtoAPtrQ = psTxDtoAStartQ;
	}

	return subbuff_toggle;
}

void
send_2mbps_2(
                struct HS_PhyTx11bStr  *HS_PhyTx11bPtrTh1,
                hs_int16_t *ssDQPSKTbl,
                hs_uint16_t *usDQPSKNew,
                ePHYSTATES_TH  *ePhyState,
                hs_int16_t * psTxDtoAStartI,
                hs_int16_t * psTxDtoAStartQ,
                hs_uint16_t usLength
             )
{
	//hs_int16_t zeros[16]= {0};
    hs_uint16_t usDiffSymbIndex;
	hs_int32_t	siPayloadBitCount;
    hs_uint8_t ucInputBit;
	hs_uint8_t ucPrevSymb;
	hs_int32_t symbol_count;
    hs_int32_t subbuff_toggle;
	hs_uint8_t *ucInputBit_shared;

    hs_int16_t * psTxOut;
    hs_int16_t * psTxOutDtoAPtrI;
    hs_int16_t * psTxOutDtoAPtrQ;

    hs_int32_t input_toggle;
	hs_int32_t i, im;

	input_toggle = 0;
	siPayloadBitCount = 0;
	ucPrevSymb = HS_PhyTx11bPtrTh1->ucPrevSymb;

	ucInputBit_shared = HS_PhyTx11bPtrTh1->ucInputBit_shared_2_55;

	psTxOutDtoAPtrI = HS_PhyTx11bPtrTh1->psTxDtoABufferI;
    psTxOutDtoAPtrQ = HS_PhyTx11bPtrTh1->psTxDtoABufferQ;

    subbuff_toggle = HS_PhyTx11bPtrTh1->subbuff_toggle;
    symbol_count = 0;

    while(1){
    	//printf("test send2 step1\n");
    	while(tx_thread1to2_flag1 == 0){
    		SPIN(2);
        }
    	START_CLOCK
		for(i=0; i<4; i++){

			ucInputBit = ucInputBit_shared[input_toggle*4+i];
			usDiffSymbIndex = usDQPSKNew[ucPrevSymb + (ucInputBit <<2)];
			ucPrevSymb = usDiffSymbIndex;

			psTxOut = &(ssDQPSKTbl[usDiffSymbIndex*2*DUAL_BUF_QUARTER_SIZE]);
//			for(im = 0; i < 22; i++) {
//				printf("psTxOut = %x\n",psTxOut[i]);
//			}

			__sb_rcopy(psTxOutDtoAPtrI, psTxOut);
			__sb_rcopy(psTxOutDtoAPtrI+16, psTxOut+16);
			__sb_rcopy(psTxOutDtoAPtrQ, psTxOut+24);
			__sb_rcopy(psTxOutDtoAPtrQ+16, psTxOut+24+16);

			psTxOutDtoAPtrI += (22);
			psTxOutDtoAPtrQ += (22);
		}
		input_toggle ^= 1;
		//printf("test send2 step2\n");
		siPayloadBitCount += 8;
		symbol_count += 4;

		if(symbol_count == 8){

			symbol_count = 0;
			subbuff_toggle = wait_buffer(subbuff_toggle,
    									&psTxOutDtoAPtrI,
    									&psTxOutDtoAPtrQ,
    									psTxDtoAStartI,
    									psTxDtoAStartQ
								);
		}

		tx_thread1to2_flag1 = 0;
		//printf("test send2 step3\n");
        if(siPayloadBitCount == (usLength*8))
        {
        	PRINT_CYCLES("send_2mbps_2");
        	*ePhyState  = PHY_STATE_SWITCH_OFF_TH;
           break;
        }/* if siStateCount */

    }

    /** Wait till last sub-buffer is Txmitted **/
    #ifndef PHY_RX_CYCLE_PRINT
	wait_sub_buffer_filled();
	reset_sub_buffer_interrupt();
	#endif

	/** Wait for remaining samples **/
	if(symbol_count != 0){
		hs_uint32_t d2a_base = ICR_ADDRESS_CORE_CHANNEL(TX_CORE, TX_PSD);

		while(ICR_GET(d2a_base, REG_D2AISTR) < ((hs_uint32_t)(psTxOutDtoAPtrI+4) & 0x0fffff)){
			__sb_barrier();
		}
	}

	HS_PhyTx11bPtrTh1->tx_status_l = HS_COMPLETE;
}


void
send_55mbps_2(
                struct HS_PhyTx11bStr  *HS_PhyTx11bPtrTh,
                ePHYSTATES_TH  *ePhyState,
                hs_uint16_t *usDQPSKNew
            )
{
	hs_int32_t i;
	hs_int32_t input_toggle;
	hs_int32_t tempreg_toggle;
	hs_uint32_t *uiTempReg_shared;
    hs_uint16_t usDiffSymbIndex;
    hs_uint8_t ucInputBit;
    hs_uint8_t *ucInputBit_shared;
    hs_uint8_t ucPrevSymb;
    hs_uint16_t usLength;
	hs_int32_t siPayloadBitCount;

	//int tic1, tic2;

    uiTempReg_shared = HS_PhyTx11bPtrTh->uiTempReg_shared;
    ucPrevSymb = HS_PhyTx11bPtrTh->ucPrevSymb;
    usLength = HS_PhyTx11bPtrTh->usLength;

	siPayloadBitCount = 0;

	ucInputBit_shared = HS_PhyTx11bPtrTh->ucInputBit_shared_2_55;
	input_toggle = 0;
	tempreg_toggle = 0;

    while(1){
    	while(tx_thread1to2_flag1 == 0){
    		SPIN(2);
        }

    	//tic1 = __sb_cfsr(MACH_CYC);

    	for(i=0; i<2; i++){
	        ucInputBit = ucInputBit_shared[2*input_toggle+i];
			usDiffSymbIndex = usDQPSKNew[ucPrevSymb + ((ucInputBit & 0x3) <<2)];
			ucPrevSymb = usDiffSymbIndex;
			uiTempReg_shared[tempreg_toggle*2+i] = ((ucInputBit & 0xC) + usDiffSymbIndex) << 5 ;
    	}

    	//tic2 = __sb_cfsr(MACH_CYC);
    	//__putstring("cyc = %d\n", tic2-tic1);

    	while(tx_thread2to3_flag1 != 0){
    		SPIN(2);
        }
    	tx_thread2to3_flag1 = 1;

		tx_thread1to2_flag1 = 0;

		tempreg_toggle ^= 1;
    	input_toggle ^= 1;

		siPayloadBitCount += 8;
        if(siPayloadBitCount == (usLength*8))
        {
        	*ePhyState  = PHY_STATE_SWITCH_OFF_TH;
           break;
        }/* if siStateCount */
    }
}

void
send_11mbps_2(
                struct HS_PhyTx11bStr  *HS_PhyTx11bPtrTh1,
                ePHYSTATES_TH	*ePhyState,
                hs_uint8_t (*scrambytetable_11)[16]
            )
{
	hs_uint8_t 	*crc_shared;
	hs_int32_t  crc_count;
    hs_uint8_t 	ucBit;
    hs_uint8_t 	ucBit1;
    hs_uint8_t 	ucInputBit;
    hs_uint8_t 	ucInputBit1;
    hs_uint8_t 	ucInputBit2;
    hs_int32_t 	payload_bytes;
    hs_uint8_t ucScramState;
    hs_uint16_t usLength;
    hs_uint8_t	*psPayloadByte;
    hs_int32_t 	input_toggle;
    hs_uint8_t *ucInputBit_shared;
    hs_int32_t flip_flag;

	//int tic1, tic2;

    crc_shared = HS_PhyTx11bPtrTh1->crc_shared;
    ucInputBit_shared = HS_PhyTx11bPtrTh1->ucInputBit_shared_11;
    ucScramState = HS_PhyTx11bPtrTh1->ucScramState;
    usLength = HS_PhyTx11bPtrTh1->usLength;
    psPayloadByte = (hs_uint8_t*)HS_PhyTx11bPtrTh1->psPayloadByte;

    input_toggle = 0;
    payload_bytes = 0;
	crc_count = 0;
	flip_flag = 0;

	while(tx_thread1to2_flag1 == 0){
		SPIN(2);
	}
	tx_thread1to2_flag1 = 0;

    while(payload_bytes < usLength-4){

    	//tic1 = __sb_cfsr(MACH_CYC);

        ucBit = psPayloadByte[payload_bytes];
        ucBit1 = ucBit&0xF;
        ucInputBit1 =  scrambytetable_11[ucScramState][ucBit1];
        ucScramState = scrambytetable_11[256+ucScramState][ucBit1];
        ucBit1 = ucBit>>4;
        ucInputBit2 =  scrambytetable_11[ucScramState][ucBit1];
        ucScramState = scrambytetable_11[256+ucScramState][ucBit1];
        ucInputBit = (ucInputBit2 << 4) | ucInputBit1;
        if(flip_flag == 1){
        	ucInputBit ^= 0x3;
        }
        ucInputBit_shared[input_toggle] = ucInputBit;

		//tic2 = __sb_cfsr(MACH_CYC);
		//__putstring("cyc = %d\n", tic2-tic1);

		while(tx_thread2to3_flag1 != 0){
			SPIN(2);
        }

        tx_thread2to3_flag1 = 1;

        flip_flag ^= 1;
        input_toggle ^= 1;
		payload_bytes++;
    }

    while(payload_bytes < usLength){

    	//tic1 = __sb_cfsr(MACH_CYC);

		ucBit = crc_shared[crc_count];
        crc_count++;

        ucBit1 = ucBit&0xF;
        ucInputBit1 =  scrambytetable_11[ucScramState][ucBit1];
        ucScramState = scrambytetable_11[256+ucScramState][ucBit1];
        ucBit1 = ucBit>>4;
        ucInputBit2 =  scrambytetable_11[ucScramState][ucBit1];
        ucScramState = scrambytetable_11[256+ucScramState][ucBit1];
        ucInputBit = (ucInputBit2 << 4) | ucInputBit1;

        if(flip_flag == 1){
        	ucInputBit ^= 0x3;
        }
        ucInputBit_shared[input_toggle] = ucInputBit;

		//tic2 = __sb_cfsr(MACH_CYC);
		//__putstring("cyc = %d\n", tic2-tic1);

		while(tx_thread2to3_flag1 != 0){
			SPIN(2);
        }

        tx_thread2to3_flag1 = 1;

        flip_flag ^= 1;
        input_toggle ^= 1;
		payload_bytes++;
    }

    *ePhyState  = PHY_STATE_SWITCH_OFF_TH;
};


void
FnThread22(void *t)
{
  hs_uint16_t usLength;

  hs_int16_t *psTxDtoAStartI;
  hs_int16_t *psTxDtoAStartQ;

  ePHYSTATES_TH  ePhyState;

  /* Tx Variables */
  struct HS_PhyTx11bStr  *HS_PhyTx11bPtrTh1;

  HS_PhyTx11bPtrTh1 = &sPhyTx11bStr;

  psTxDtoAStartI = HS_PhyTx11bPtrTh1->psTxDtoAStartI;
  psTxDtoAStartQ = HS_PhyTx11bPtrTh1->psTxDtoAStartQ;

  //printf("testf22\n");

  while(tx_data_flag2 == 0){
	  SPIN(2);
  }
  tx_data_flag2 = 0;

  ePhyState = (ePHYSTATES_TH)HS_PhyTx11bPtrTh1->ePhyState;

  usLength = HS_PhyTx11bPtrTh1->usLength;

  //printf("testf22\n");

  switch(ePhyState)
  {
  	 case PHY_STATE_TX_SEND_PAYLOAD_2MBPS_TH:
     {
         send_2mbps_2(
                HS_PhyTx11bPtrTh1,
                ssDQPSKTbl,
                usDQPSKNew,
                &ePhyState,
                psTxDtoAStartI,
                psTxDtoAStartQ,
                usLength
             );

         break;
     }/* case PHY_STATE_TX_SEND_PAYLOAD_2MBPS_TH */

     case PHY_STATE_TX_SEND_PAYLOAD_5DOT5MBPS_TH:
     {
         send_55mbps_2(
            HS_PhyTx11bPtrTh1,
            &ePhyState,
            usDQPSKNew
         );

        break;
     }/* case PHY_STATE_TX_SEND_PAYLOAD_5DOT5MBPS_TH */

     case PHY_STATE_TX_SEND_PAYLOAD_11MBPS_TH:
     {
    	 send_11mbps_2(
    	                 HS_PhyTx11bPtrTh1,
    	                 &ePhyState,
    	                 scrambytetable_11
    	             );

        break;
     }/* case PHY_STATE_TX_SEND_PAYLOAD_11MBPS_TH */

     /* ********************************* TX_ENDS ******************* */

     case PHY_STATE_SWITCH_OFF_TH:
     {
         break;
     }/* case PHY_STATE_SWITCH_OFF_TH */

     default:
    	 break;

  }/* switch ePhyState */

}/* Function */
